package com.fishery.authority.filter;

import com.alibaba.fastjson.JSON;
import com.fishery.authority.entity.*;
import com.fishery.authority.mapper.FunctionMapper;
import com.fishery.authority.service.FunctionRoleService;
import com.fishery.authority.service.FunctionService;
import com.fishery.authority.service.UserRoleService;
import com.fishery.authority.service.UserService;
import com.fishery.authority.utils.ResponseUtil;
import com.fishery.authority.utils.SecurityContextUtil;
import com.fishery.entity.Result;
import com.fishery.util.TokenManager;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

/**
 * <p>
 * 访问过滤器
 * </p>
 *
 * @author 711
 * @since 2021-01-13
 */
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {

    private TokenManager tokenManager;
    private RedisTemplate redisTemplate;
    private FunctionService functionService;
    private UserService userService;
    private UserRoleService userRoleService;
    private FunctionRoleService functionRoleService;
    private FunctionMapper functionMapper;
//
//    @Autowired
//    private TokenManager tokenManager;
//    @Autowired
//    private RedisTemplate redisTemplate;
//    @Autowired
//    private FunctionService functionService;
//    @Autowired
//    private UserService userService;
//    @Autowired
//    private AdminService adminService;
//    @Autowired
//    private UserRoleService userRoleService;
//    @Autowired
//    private FunctionRoleService functionRoleService;

    public TokenAuthenticationFilter(AuthenticationManager authManager) {
        super(authManager);
    }


    public TokenAuthenticationFilter(AuthenticationManager authManager,
                                     TokenManager tokenManager,
                                     RedisTemplate redisTemplate,
                                     FunctionService functionService,
                                     UserRoleService userRoleService,
                                     UserService userService,
                                     FunctionRoleService functionRoleService,
                                     FunctionMapper functionMapper) {
        super(authManager);
        this.tokenManager = tokenManager;
        this.redisTemplate = redisTemplate;
        this.functionService = functionService;
        this.redisTemplate = redisTemplate;
        this.userService = userService;
        this.userRoleService = userRoleService;
        this.functionRoleService = functionRoleService;
        this.functionMapper = functionMapper;
    }


    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 这uri不用经过处理
        String reqURI = req.getRequestURI();
        if (!reqURI.equals("/authority/user/login") &&
                !reqURI.equals("/authority/user/register") &&
                !reqURI.equals("/authority/user/loginByPhone") &&
//                !reqURI.equals("/admin/login") &&
//                !reqURI.equals("/authority/user/retrievePassword") &&
//                !reqURI.equals("/function") &&
                !reqURI.equals("/captcha/getCaptcha") &&
                !Pattern.matches("/captcha/.+?", reqURI) &&
                !Pattern.matches("authority/user/retrievePassword/.+?", reqURI) &&
                !reqURI.startsWith("/authority/user/retrievePassword/") &&
                !Pattern.matches("/authority/user/register/.+", reqURI) &&
                !Pattern.matches("/authority/user/updatePassword/.+", reqURI)) {
            // 获取请求头中JWT的Token
            String tokenHeader = req.getHeader("Authorization");
            if (null != tokenHeader && tokenHeader.startsWith("Bearer ")) {
                // 截取JWT前缀
                String token = tokenHeader.replace("Bearer ", "");
                // 解析JWT
                Claims claims = tokenManager.parseJWT(token);

                // 获取过期时间
                Date expiration = claims.getExpiration();

                // 若距离过期时间小于5分钟，刷新token
                if (expiration.getTime() - System.currentTimeMillis() < 300000) {
                    token = tokenManager.updateJWT(token);
                }

                // 每次访问接口总是返回未过期或者刷新过的token
                // 把token放入相应体中
                ResponseUtil.placeToken(response,token);

                // 获取token里面的信息，再进行封装成一个UserDetails实例
                String userId = claims.getId();

                if (!StringUtils.isEmpty(userId)) {
                    List<Function> functionList = null;
                    List<Function> functionList1 = functionMapper.findByRoleIdByUserId(userId);
//                    functionList = functionList1;
                    functionList = functionMapper.findByRoleIdByUserId(userId);
                    List<GrantedAuthority> authorities = new ArrayList();
                    if (functionList != null && functionList.size() != 0) {
                        functionList.forEach(function -> authorities.add(new SimpleGrantedAuthority(function.getName())));
                    }
                    // 组装参数
                    UserDetailsImpl userDetailsImpl = new UserDetailsImpl();
                    userDetailsImpl.setUsername(claims.getSubject());
                    userDetailsImpl.setId(claims.getId());
                    userDetailsImpl.setAuthorities(authorities);
                    // 对用户进行认证，直接把用户的信息和用户的权限直接交给Authentication的实例
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetailsImpl, userId, authorities);
                    // Authentication放入安全上下文中
                    SecurityContextUtil.setAuthentication(authentication);
                }
            } else {
                // 抛出后被下面的catch捕获
                try {
                    throw new Exception();
                } catch (Exception e) {
                    ResponseUtil.write(response, JSON.toJSONString(Result.error("未登录")));
                }
            }
        }
        // 放行
        chain.doFilter(req, response);
    }

//    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest req) {
//        // token置于header里
//        String token = req.getHeader("token");
//        if (token != null && !"".equals(token.trim())) {
//            //获取用户名
//            String userName = tokenManager.getUserFromToken(token);
//            //获取权限
//            List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(userName);
//            //List转Collection<? extends GrantedAuthority>
//            Collection<GrantedAuthority> authorities = new ArrayList<>();
//            for(String permissionValue : permissionValueList) {
//                if(StringUtils.isEmpty(permissionValue)) continue;
//                SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
//                authorities.add(authority);
//            }
//
//            if (!StringUtils.isEmpty(userName)) {
//                return new UsernamePasswordAuthenticationToken(userName, token, authorities);
//            }
//            return null;
//        }
//        return null;
//    }
}